package com.sec.etech.process.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sec.etech.process.mapper.SppRouteOpMapper;
import com.sec.etech.process.model.*;
import com.sec.etech.sys.util.DbUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.openbpm.base.core.id.IdUtil;
import org.openbpm.base.core.util.StringUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Service
public class SppRouteOpService extends ServiceImpl<SppRouteOpMapper, SppRouteOp> {
    @Resource
    private SppRouteStepService sppRouteStepService;
    @Resource
    private SppRelSamService sppRelSamService;
    @Resource
    private SppRelToolService sppRelToolService;
    @Resource
    private SppRelFileService sppRelFileService;

    //行编辑校验工序号是否重复
    public String checkOpNo(JSONObject object){
        Map<String, String> opNoMap = new HashMap<>();//工序号
        Map<String, Integer> opNoNumMap = new HashMap<>();//工序号以及数量
        Long routeRevId = object.getLong("route_rev_id");
        //查询数据库
        List<SppRouteOp> opList = super.list(new LambdaQueryWrapper<SppRouteOp>().eq(SppRouteOp::getRouteRevId, routeRevId));
        if(opList!=null && opList.size()>0){
            for(SppRouteOp op:opList){
                opNoMap.put(op.getRouteOpId().toString(), op.getOpNo());
            }
        }
        //查询待保存/更新对象
        List<JSONObject> objectList = (List<JSONObject>) object.get("dataList");
        for (JSONObject obj : objectList) {
            String flag = obj.getString("flag");
            String routeOpId = obj.getString("route_op_id") != null ? obj.getString("route_op_id") : null;
            if(!"del".equals(flag)){//删除
                String opNo = obj.getString("op_no");
                if (StringUtil.isNotEmpty(routeOpId)) {
                    opNoMap.put(routeOpId, opNo);
                }
            }else {
                opNoMap.remove(routeOpId);
            }
        }
        //检查已有ID的工序是否重复
        for(Map.Entry<String, String> entry:opNoMap.entrySet()) {
            if(opNoNumMap.containsKey(entry.getValue())) {
                Integer num = opNoNumMap.get(entry.getValue());
                opNoNumMap.put(entry.getValue(), num + 1);
            }else {
                opNoNumMap.put(entry.getValue(), 1);
            }
        }
        //检查新增/修改工序卡中是否有工序号重复
        for (JSONObject obj : objectList) {
            if("01".equals(obj.getString("step_no")) && (obj.getLong("route_step_id") == null || obj.getLong("route_step_id") == 0)){
                String opNo = obj.getString("op_no");
                if (opNoNumMap.containsKey(opNo)) {
                    Integer num = opNoNumMap.get(opNo);
                    //解决插入01工步提示工序重复问题
                    if(obj.getLong("route_op_id")==null || obj.getLong("route_op_id")==0){
                        opNoNumMap.put(opNo, num + 1);
                    }
                } else {
                    opNoNumMap.put(opNo, 1);
                }
            }
        }
        String msg = "";
        for(Map.Entry<String, Integer> entry:opNoNumMap.entrySet()) {
            if(entry.getValue()>1){
                msg = entry.getKey() + "、" + msg;
            }
        }
        if(!"".equals(msg)){
            return "该工序号已存在，无法修改：" + msg.substring(0, msg.length()-1);
        }
        return "success";
    }
    //路线卡行编辑
    public void saveOrUpdateByObject(JSONObject object, Long routeRevId, String module) throws Exception {
        SppRouteStep step = JSONObject.toJavaObject(object, SppRouteStep.class);
        String flag = object.getString("flag");

        if(StringUtil.isNotEmpty(object.getString("amendnum"))) {//修改单号处理
            if(step.getRouteStepId()==null || step.getRouteStepId()==0) {
                step.setAmends(object.getString("amendnum"));
            }else {
                SppRouteStep dbStep = sppRouteStepService.getById(step.getRouteStepId());
                String dbAmends = dbStep!=null ? dbStep.getAmends() : null;
                if (StringUtil.isEmpty(dbAmends)) {
                    step.setAmends(object.getString("amendnum"));
                } else if (!dbAmends.contains(object.getString("amendnum"))) {
                    step.setAmends(dbAmends + "；" + object.getString("amendnum"));
                }
            }
        }
        // 删除功能已迁移到单独的迁移方法
        if("del".equals(flag)){//删除
            if("01".equals(step.getStepNo())){//删除工序和所属工步
                this.delOperation(step, object.getString("amendnum"));
            }else {//删除工步
                sppRouteStepService.delStep(step, object.getString("amendnum"));
                //sppRouteStepService.removeById(step.getRouteStepId());
            }
        }else if (step.getRouteStepId() == null || step.getRouteStepId() == 0) {//新增
            if((object.getLong("route_op_id")==null || object.getLong("route_op_id")==0)
                    && "01".equals(step.getStepNo())) {//新增工序
                SppRouteOp op = new SppRouteOp();
                op.setRouteOpId(IdUtil.getUId());
                op.setOpNo(object.getString("op_no"));
                op.setRouteRevId(routeRevId);
                op.setOpTextId(step.getOpTextId());
                super.save(op);
                step.setRouteOpId(op.getRouteOpId());
            }
            if(!"01".equals(step.getStepNo())){
                step.setOpTextId(null);
            }
            step.setStepNum(sppRouteStepService.getStepNum(object.getString("op_no"), step.getStepNo()));
            step.setRouteStepId(IdUtil.getUId());
            step.setRouteRevId(routeRevId);
            sppRouteStepService.save(step);
        } else {//更新
            if("01".equals(step.getStepNo())) {//更新工序
                SppRouteOp op = new SppRouteOp();
                op.setRouteOpId(step.getRouteOpId());
                op.setOpNo(object.getString("op_no"));
                op.setOpTextId(step.getOpTextId());
                super.updateById(op);
            }else {
                step.setOpTextId(null);
            }
            step.setStepNum(sppRouteStepService.getStepNum(object.getString("op_no"), step.getStepNo()));
            if("routeDetailWorkingHours".equals(module)){//工时修改同步工时信息
                //workHourStepService.updateWorkHourById(step.getRouteStepId(), step.getWorkinghours());
            }
            sppRouteStepService.updateById(step);
        }
    }
    //新增工序/工步
    public void createOperationAndStep(Long routeRevId, Long routeOpId, String amendNum){

        SppRouteStep routeStep = new SppRouteStep();
        routeStep.setRouteStepId(IdUtil.getUId());
        routeStep.setRouteRevId(routeRevId);
        routeStep.setAmends(amendNum);
        if(routeOpId!=null && routeOpId>0) {
            SppRouteOp routeOpDb = super.getById(routeOpId);
            routeStep.setRouteOpId(routeOpDb.getRouteOpId());
            routeStep.setOpTextId(routeOpDb.getOpTextId());
            // 插入工步，取当前工序下工步最大值+1
            String sql = "select max(step_num) maxNum from spp_route_step where route_op_id=?";
            List<Map<String, Object>> stepList = DbUtil.getJdbcTemplate().queryForList(sql, routeOpId);
            String maxNum = (stepList!=null && stepList.size()>0 && stepList.get(0).get("maxNum")!=null) ? stepList.get(0).get("maxNum").toString() : "000000";
            routeStep.setStepNo(String.format("%02d", Integer.parseInt(maxNum.substring(3)) + 1));
            routeStep.setStepNum(sppRouteStepService.getStepNum(routeOpDb.getOpNo(), routeStep.getStepNo()));
        }else {//新增工序
            String sql = "select max(cast(op_no as signed)) maxOpNo from spp_route_op where route_rev_id=?";
            List<Map<String, Object>> opList = DbUtil.getJdbcTemplate().queryForList(sql, routeRevId);
            String maxOpNo = (opList!=null && opList.size()>0 && opList.get(0).get("maxOpNo")!=null) ? opList.get(0).get("maxOpNo").toString() : "00";

            SppRouteOp routeOp = new SppRouteOp();
            routeOp.setRouteOpId(IdUtil.getUId());
            routeOp.setRouteRevId(routeRevId);
            routeOp.setOpNo(String.format("%02d", Integer.parseInt(maxOpNo) + 1));
            super.save(routeOp);

            routeStep.setStepNo("01");
            routeStep.setStepNum(sppRouteStepService.getStepNum(routeOp.getOpNo(), routeStep.getStepNo()));
            routeStep.setRouteOpId(routeOp.getRouteOpId());
        }
        sppRouteStepService.save(routeStep);
    }
    //删除工序
    public void delOperation(SppRouteStep step, String amendNum){
        Long roteRevId = step.getRouteRevId();
        Long routeOpId = step.getRouteOpId();
        // 修改单 修改原有记录时逻辑删除, 待优化，考虑到修改单存在历史版本，此问题不紧急
        boolean needLogicDel = false;
//        String checkAmdRouteSql = "select count(1) as c1 from proc_parts_tech_amend t " +
//                " where t.change_mode=2 and  t.new_target_id=" + step.getRouteRevId();
//        int c1 = DbUtil.getJdbcTemplate().queryForObject(checkAmdRouteSql, Integer.class);
//        if(c1>0){
//            // 路线卡修改
//            // 不考虑新增后再删除的情况
//            needLogicDel = true;
//        }
        if(needLogicDel){
            // TODO 逻辑删除，加上修改单号
            //  String delSql1 = "update spp_route_step set active=0 where route_op_id=";
            //  String delSql2 = "update spp_route_op set active=0 where route_op_id=";
            sppRouteStepService.remove(new LambdaQueryWrapper<SppRouteStep>().eq(SppRouteStep::getRouteOpId, routeOpId));
            super.removeById(routeOpId);
        }else{
            sppRouteStepService.remove(new LambdaQueryWrapper<SppRouteStep>().eq(SppRouteStep::getRouteOpId, routeOpId));
            super.removeById(routeOpId);
        }
        // 工序重排序
        try{
            reorderRouteOp(roteRevId, routeOpId);
        }catch(Exception ex){
            log.warn("删除工序后重排序出错:"+ex.getMessage());
        }
    }

    public void reorderRouteOp(Long roteRevId, Long routeOpId){
        // 路线卡工序重排序，不重排序工序卡工步，但需要更新工步的stepNum

        // 增加废弃工序记录的检查，设置无工步的工序记录 active=0
        try{
            String checksql = "update spp_route_op op set op.active=0 " +
                    " where op.active=1 and op.route_rev_id=" + roteRevId +
                    " and not EXISTS(select step.route_step_id from spp_route_step step where step.route_op_id=op.route_op_id and step.active=1)";
            DbUtil.getJdbcTemplate().execute(checksql);
        }catch(Exception e){
            log.warn(e.getMessage());
        }

        //
        String sql = "select route_op_id, op_no from spp_route_op where route_rev_id=? and active=1";
        List<Map<String, Object>> opList = DbUtil.getJdbcTemplate().queryForList(sql, roteRevId);
        if(CollectionUtils.isEmpty(opList)){
            return;
        }
        // 按照工序号排序
        CollectionUtil.sort(opList, new Comparator<Map<String, Object>>(){
            @Override
            public int compare(Map<String, Object> op1, Map<String, Object> op2) {
                String opNo1 = MapUtil.getStr(op1, "op_no");
                if(ObjectUtils.isEmpty(opNo1)){
                    return -1;
                }
                String opNo2 = MapUtil.getStr(op2, "op_no");
                //防止同时存在2位和3位序号的情况
                return Integer.parseInt(opNo1) - Integer.parseInt(opNo2);
            }
        });
        // 检查排序后需要更新的记录
        List<Object[]> batchArgs = new ArrayList<Object[]>();
        List<Object[]> batchArgs2 = new ArrayList<Object[]>();
        for(int i=0; i<opList.size(); i++){
            String newOpNo = String.format("%02d", i+1);
            Map<String, Object> op = opList.get(i);
            String opNo = MapUtil.getStr(op, "op_no");
            if(!newOpNo.equals(opNo)){
                routeOpId = MapUtil.getLong(op,"route_op_id");
                batchArgs.add(new Object[]{newOpNo, routeOpId});
                // 需要更新该工序下工步的step_num字段
                String sql2 = "select route_step_id, step_no, step_num from spp_route_step where route_op_id=? and active=1";
                List<Map<String, Object>> stepList = DbUtil.getJdbcTemplate().queryForList(sql2, routeOpId);
                for(Map<String, Object> step: stepList){
                    batchArgs2.add(new Object[]{
                            String.format("%03d", i+1) + String.format("%03d", Integer.parseInt(step.get("step_no").toString())),
                            //String.format("%3s%3s", i+1, MapUtil.getStr(op, "step_no")).replaceAll(" ","0")
                            MapUtil.getLong(step,"route_step_id")});
                }
            }
        }
        // 批量更新工序
        String updateSql = "update spp_route_op set op_no=? where route_op_id=?";
        if(CollectionUtils.isNotEmpty(batchArgs)){
            DbUtil.getJdbcTemplate().batchUpdate(updateSql, batchArgs);
        }
        // 批量更新工步
        String updateSql2 = "update spp_route_step set step_num=? where route_step_id=?";
        if(CollectionUtils.isNotEmpty(batchArgs2)){
            DbUtil.getJdbcTemplate().batchUpdate(updateSql2, batchArgs2);
        }
    }
    //从路线卡复制
    public void copyFromRouteCard(Long fromRouteRevId, Long toRouteRevId, String amends, boolean copy, boolean copyFile){
        //先删除工序和工步
        super.remove(Wrappers.<SppRouteOp>lambdaUpdate().eq(SppRouteOp::getRouteRevId, toRouteRevId));
        sppRouteStepService.remove(Wrappers.<SppRouteStep>lambdaUpdate().eq(SppRouteStep::getRouteRevId, toRouteRevId));
        //复制工序
        Map<String, SppRouteOp> routeOpIdMap = new HashMap<>();
        List<SppRouteOp> fromOpList = super.list(new LambdaQueryWrapper<SppRouteOp>().eq(SppRouteOp::getRouteRevId, fromRouteRevId));
        if(fromOpList!=null && fromOpList.size()>0){
            for(SppRouteOp op:fromOpList){
                SppRouteOp toOp = new SppRouteOp();
                BeanUtil.copyProperties(op, toOp);
                toOp.setRouteOpId(IdUtil.getUId());
                toOp.setRouteRevId(toRouteRevId);
                super.save(toOp);
                routeOpIdMap.put(op.getRouteOpId().toString(), toOp);
            }
        }
        //复制工步
        List<SppRouteStep> fromStepList = sppRouteStepService.list(new LambdaQueryWrapper<SppRouteStep>()
                .eq(SppRouteStep::getRouteRevId, fromRouteRevId));
        if(fromStepList!=null && fromStepList.size()>0){
            for(SppRouteStep step:fromStepList){
                SppRouteStep toStep = new SppRouteStep();
                BeanUtil.copyProperties(step, toStep);
                toStep.setRouteStepId(IdUtil.getUId());
                SppRouteOp toOp = routeOpIdMap.get(step.getRouteOpId().toString());
                toStep.setRouteOpId(toOp.getRouteOpId());
                toStep.setStepNum(sppRouteStepService.getStepNum(toOp.getOpNo(), step.getStepNo()));
                toStep.setRouteRevId(toRouteRevId);
                if(!copy) {
                    toStep.setAmends(amends);
                }
                toStep.setRemark("");
                if(StringUtil.isEmpty(amends)) {//编制的复制
                    toStep.setOperationCard(null);
                }
                toStep.setChangeOp(0);
                sppRouteStepService.save(toStep);
                //复制关联的标准
                List<SppRelSam> samList = sppRelSamService.getRefSamList(step.getRouteRevId(), 1, step.getRouteStepId());
                for(SppRelSam sam:samList) {
                    SppRelSam toSam = new SppRelSam();
                    BeanUtil.copyProperties(sam, toSam);
                    toSam.setRelSamId(IdUtil.getUId());
                    toSam.setTargetId(toStep.getRouteRevId());
                    toSam.setStepId(toStep.getRouteStepId());
                    sppRelSamService.save(toSam);
                }
                //复制关联的工装
                List<SppRelTool> toolList = sppRelToolService.getRefToolList(step.getRouteRevId(), 1, step.getRouteStepId());
                for(SppRelTool tool:toolList) {
                    SppRelTool toTool = new SppRelTool();
                    BeanUtil.copyProperties(tool, toTool);
                    toTool.setRelToolId(IdUtil.getUId());
                    toTool.setTargetId(toStep.getRouteRevId());
                    toTool.setStepId(toStep.getRouteStepId());
                    sppRelToolService.save(toTool);
                }
            }
        }
        if (copyFile) {
            //复制文件附件
            List<SppRelFile> refFileList = sppRelFileService.getRefFileList(fromRouteRevId, 1);
            for(SppRelFile file:refFileList) {
                SppRelFile toFile = new SppRelFile();
                BeanUtil.copyProperties(file, toFile);
                toFile.setRelFileId(IdUtil.getUId());
                toFile.setTargetId(toRouteRevId);
                sppRelFileService.save(toFile);
            }
        }
    }
}
